#!/usr/bin/python
import os
import sys
import MySQLdb
import string
import time
import cloud
import db
import pp
import remoteExeCommand

def isDigtal(Num):
    nums = string.digits
    myNum = str(Num)
    if type(myNum) is not str:
        return False
    else:
        for temp in myNum:
            if temp not in nums:
                return False
        return True
        

def checkMpiCPara(conn,env_id,mpifile,inputFile):
    try:  
        if not conn:
            #print "Can not connect to database, Fail!"
            return -1
        if not isDigtal(env_id):
            return -2
    
        flag,rows = db.exeFetchCommand(conn,"select env_id from mpi_env where env_id = " + str(env_id));
	
        if flag == 0:
            #print "No Job ", env_id
            return -2
   	 
        flag = os.path.exists(mpifile)
        if not flag:
            #print "File "+mpifile+" is not exist."
            return -2
        for eachfile in inputFile:
            flag = os.path.exists(eachfile)
            if not flag:
                return -2
        return 1
    except:
        return -5

def send_date_to_master(remote_address,username,local_data_path,remote_data_path):
    #command="scp " + local_data_path + " " + username+"@"+remote_address +":"+ remote_data_path
    #out = os.popen(command)
    #print out.read()
    flag,result = remoteExeCommand.scpCmd(remote_address,local_data_path,remote_data_path,username)
    return not flag,result

def makedir(remote_address,username,optPath):
    command = "\"mkdir " + optPath + "\""
    flag,result = remoteExeCommand.sshCmd(remote_address,username,command)
    return not flag

def sendfile(remote_address,username,mpiSource,inputFile,optPath):
    #print remote_address
    path=optPath  
    local_data_path = mpiSource
    remote_data_path=path +"/"
    tmp = local_data_path.split("/")
    remote_data_path+=tmp[-1] 
    mpiFile = remote_data_path
    #print username, local_data_path, " ", remote_data_path
    flag,result = send_date_to_master(remote_address,username,local_data_path,remote_data_path)
    #print flag, result
    if not flag:
        return flag, mpiFile
    
    for eachfile in inputFile:
        local_data_path = eachfile
        remote_data_path=path +"/"
        tmp = local_data_path.split("/")
        remote_data_path+=tmp[-1] 
        flag = send_date_to_master(remote_address,username,local_data_path,remote_data_path) 
        if not flag:
           return flag, mpiFile
    return flag, mpiFile,


def mpicc(masterIP,username,mpifile,exec_id,optPath):
    path = optPath
    #command = "ssh "+username+"@" + masterIP + " \"mpicc -o /home/cgcl/jobProgram " + mpifile + "\"" 
    command = "\"mpicc -o " + path + "/" + str(exec_id) + " " + mpifile + "\"" 
    mpiExe= path + "/" + str(exec_id)
    #out=os.popen(command)
    #print out.read()
    flag,result = remoteExeCommand.sshCmd(masterIP,username,command)
    #print flag, result
    return not flag, mpiExe

def launchJob(master_address,user,mpiExe,cnt,job_id,exec_id,optPath,savePath):
    path = optPath
    #command="ssh "+user+"@"+master_address + " \"mpirun -machinefile /home/cgcl/all_vm_ip_list -np "+str(cnt) + " " + mpiExe + "\"
    cddir = "cd " + path
    execmpi = "mpirun -machinefile /home/cgcl/all_vm_ip_list -np "+str(cnt) + " " + mpiExe + " > " + str(exec_id) + "_ans"
    exectar = "cd "+ savePath + "; tar zcvf "+str(exec_id)+".tar.gz ./"+ str(exec_id)
    command = "\"" + cddir + "; " + execmpi + "; " + exectar + "\""
    flag,result = remoteExeCommand.sshCmd(master_address,user,command)
    result = path + ".tar.gz"
    return not flag,result

def launch(env_id,sourceFile,inputFile):
    savePath="/home/cgcl" 
    exec_id = -1
    username="root"
    localAnsPath = "/srv/cloud/mpiAns"
    try:
        connect = db.connectDB();
        conn = db.cursorDB(connect)
        flag = checkMpiCPara(conn,env_id,sourceFile,inputFile)
        # flag = -1: database connection fail.
        # flag = -2: Parameter error.
        # flag = -5: exception
        if flag < 0:
            db.closeCursor(conn)
            db.closeConnect(connect)
    	    return flag
        
        cnt = db.exeFetchCommand(conn,"insert into exec_job(env_id,source,status) values(" + str(env_id) + ",'" + str(sourceFile) + "', 'running')");
        cnt, rows = db.exeFetchCommand(conn,"select max(exec_id) from exec_job")
	exec_id = int(rows[0][0])
                
        cnt,rows = db.exeFetchCommand(conn,"select vm_ip from env_resource, vm_info where env_id="+str(env_id)+" and env_resource.vm_id=vm_info.vm_id and vm_info.vm_type='master'")
        if cnt != 1:
            #print "Not Master Node,Fail!"
            db.exeSetCommand(conn,"update exec_job set status = 'fail' where exec_id = " + str(exec_id) )
            db.closeCursor(conn)
            db.closeConnect(connect)
            return -2     
        masterIP=rows[0][0]
        #print masterIP,password    
        total_VM,rows = db.exeFetchCommand(conn,"select * from env_resource where env_id = "+str(env_id))
        #print total_VM
	optPath = savePath + "/" + str(exec_id)
        
        flag = makedir(masterIP,username,optPath)
        if not flag:
            return -6
        #print "Send " + sourceFile + " to masterNode ..."
        flag,mpiFile = sendfile(masterIP,"root",sourceFile,inputFile,optPath)
        #print " -flag = ", flag, mpiFile
        if not flag:
            db.exeSetCommand(conn,"update exec_job set status = 'fail' where exec_id = " + str(exec_id) )
            db.closeCursor(conn)
            db.closeConnect(connect)
            return -6
        #print "mpicc Complie " + mpiFile + " to execute file[name: jobProgram] ..."
        #print mpiFile
        flag,mpiExe = mpicc(masterIP,"root",mpiFile,exec_id,optPath)
        #print "mpicc flag = ", flag

        if not flag:
            db.exeSetCommand(conn,"update exec_job set status = 'fail' where exec_id = " + str(exec_id) )
            db.closeCursor(conn)
            db.closeConnect(connect)
            return -6
        time.sleep(5) 
    
        #print "mpirun execute file:"
    
        flag, result = launchJob(masterIP,"root",mpiExe,total_VM,env_id,exec_id,optPath,savePath)    
        #print "launch flag = ", flag,result
        
        if flag:
            command="scp root@"+masterIP+":" + result +" " + localAnsPath
            #print command
            res,res1 = remoteExeCommand.cmd(command)
            result = localAnsPath + "/" + str(exec_id) + ".tar.gz"
            if res:
                #print res, result
                flag = 0
        if flag:
	    db.exeSetCommand(conn,"update exec_job set status = 'finish' where exec_id = " + str(exec_id) )
            db.exeSetCommand(conn,"update exec_job set ans_path = '" + str(result) + "' where exec_id = " + str(exec_id) )
        else:
            db.exeSetCommand(conn,"update exec_job set status = 'fail' where exec_id = " + str(exec_id) )
        db.closeCursor(conn)
        db.closeConnect(connect)
        
        if flag:
            return exec_id
        return -6
    except:
        if exec_id > 0:
            connect = db.connectDB()
            conn = db.cursorDB(connect)
            db.exeSetCommand(conn,"update exec_job set status = 'fail' where exec_id = " + str(exec_id) )
            db.closeCursor(conn)
            db.closeConnect(connect)
        return -5

def getJobAns(exec_id):
    try:
        flag = isDigtal(exec_id)
        if not flag:
            return -2,""
        connect = db.connectDB()
        conn = db.cursorDB(connect)
        if not conn:
            #print "Can not connect to database, Fail!"
            return -1,""
        flag,rows = db.exeFetchCommand(conn,"select ans_path from exec_job where status = 'finish' and exec_id = " + str(exec_id));
        db.closeCursor(conn)
        db.closeConnect(connect)
        if flag == 0:
        #print "No Job ", env_id
            return -2,""
        return 1,rows[0][0]
    except:
        return -5,""


